﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Asn1;

namespace TheClerk.Forms.Templates.raw.Envelope
{
    #region internal Commitments
    /// <summary>
    /// Many hashes over Assertions
    /// </summary>
    /// <remarks>
    /// -- Multiple hashing algorithms to future-proof in case of one or several
    /// -- compromise
    /// Commitments ::= SEQUENCE(1..MAX) OF Commitment
    /// </remarks>
    internal class Commitments
    {
        List<Commitment> data = new List<Commitment>();
        private Stream assertions;

        public Commitments(Stream assertions)
        {
            this.assertions = assertions;

            // GOST R3411
            data.Add(new Commitment(Org.BouncyCastle.Asn1.CryptoPro.CryptoProObjectIdentifiers.GostR3411, assertions));
            // RIPE MD256
            data.Add(new Commitment(Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTObjectIdentifiers.RipeMD256, assertions));
            // MD5 (here for illustrative purposes)
            data.Add(new Commitment(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.MD5, assertions));
            // MD2 (also here for illustrative purposes)
            data.Add(new Commitment(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.MD2, assertions));
            // SHA-1
            data.Add(new Commitment(Org.BouncyCastle.Asn1.X509.X509ObjectIdentifiers.IdSha1, assertions));
            // SHA-2 family
            data.Add(new Commitment(Org.BouncyCastle.Asn1.Nist.NistObjectIdentifiers.IdSha384, assertions));
        }

        internal Stream Serialize()
        {
            MemoryStream s = new MemoryStream();
            var dsg = new DerSequenceGenerator(s);
            foreach (Commitment i in data)
            {
                dsg.AddObject(i.ToAsn1Encodable());
            }
            dsg.Close();
            s.Position = 0;
            return s;
        }

        public void Add(Commitment c)
        {
            data.Add(c);
        }

        internal Asn1Encodable ToAsn1Encodable()
        {
            return Asn1Object.FromStream(Serialize());
        }

        internal byte[] AsByteArray()
        {
            var s = Serialize();
            byte[] buf = new byte[s.Length];
            s.Read(buf, 0, buf.Length);
            return buf;
        }
    }
    #endregion
}
